package com.datseek.iot.rule.manager.service;

import com.alibaba.fastjson.JSON;
import com.dataseek.iot.core.util.CopyUtil;
import com.dataseek.iot.mysql.entity.ActivityRule;
import com.datseek.iot.rule.manager.annotation.Fact;
import com.datseek.iot.rule.manager.entity.DeviceMsg;
import com.datseek.iot.rule.manager.entity.RuleDTO;
import com.datseek.iot.rule.manager.entity.RuleExecutorResult;
import com.datseek.iot.rule.manager.entity.fact.BaseFact;
import com.datseek.iot.rule.manager.entity.fact.DeviceFact;
import com.datseek.iot.rule.manager.executor.RuleExecutor;
import com.datseek.iot.rule.manager.generator.RuleGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @author cc
 * @Title: 规则服务
 * @Description: 规则服务
 * @date 2021/9/176:35 下午
 * @since 1.0
 */
@Service
@Slf4j
public class RuleService {

    @Autowired
    RuleRepository ruleRepository;

    /**
     * 载入规则
     */
    public void loadRule(){
        try{
            List<RuleDTO> ruleDTOs = getActivityRuleList();
            log.info("{}条加入规则引擎", ruleDTOs.size());
            if(!ruleDTOs.isEmpty()){
                RuleGenerator generator = new RuleGenerator();
                generator.generateRules(ruleDTOs);
            }
        }catch (Exception e){
            log.error("RuleService.loadRule。e={}",e.getMessage(), e);
        }

    }

    /**
     * 触发规则
     */
    public void useRule(String clientId, String deviceId, String productId) {
        BaseFact fact = buildBaseFact(clientId, deviceId, productId);
        /**
         * 因为是uuid所以修改了的规则，重载加载是新的drl，故从数据库动态加载之时，is_delete属性要注意
         * */
        String orderId = UUID.randomUUID().toString();
        /**
         * 此处应当是从其他服务获取的的消息体，而不是空值
         * */
        DeviceMsg domain = new DeviceMsg();
//        domain.setTelephone(phone);
        try {
            /*可以知道一条信息，匹配了多少个规则，成功了几个*/
            RuleExecutorResult ruleExecutorResult = beforeExecute(orderId, fact, domain);
            log.info("RuleService|useRule|ruleExecutorResult={}", JSON.toJSON(ruleExecutorResult));
//            Assert.isTrue(ruleExecutorResult.getFailure() == 0, String.format("有%d条规则执行失败", ruleExecutorResult.getFailure()));
        } catch (Exception e) {
            log.error("RuleService|useRule|class={},orderId={}, userId={}, 规则执行异常:{}", this.getClass().getName(), orderId, "123456789", e.getMessage(), e);
        }
    }

    /**
     * 执行前
     * @param orderId
     * @param fact
     * @param domain
     * @return
     */
    private RuleExecutorResult beforeExecute(String orderId, BaseFact fact, DeviceMsg domain) {
        DeviceFact registerFact = buildDeviceFact(domain);
        CopyUtil.copyPropertiesCglib(fact, registerFact);
        log.info("RuleService|beforeExecute|{}事件的orderId={}, RegisterMqDTO={}", registerFact.getClass().getAnnotation(Fact.class).value(), orderId, domain);
        return RuleExecutor.execute(registerFact, orderId);
    }


    /**
     * 从数据库里面取规则
     */
    public List<RuleDTO> getActivityRuleList() {
        Date begin = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
        Date end = Date.from(LocalDateTime.now().plusDays(1).atZone(ZoneId.systemDefault()).toInstant());

        List<ActivityRule> list = ruleRepository.selectAll();
        List<RuleDTO> ruleDTOList = new ArrayList<>();
        for (ActivityRule dto : list) {
            RuleDTO ruleDTO = new RuleDTO();
            ruleDTO.setBeginTime(begin);
            ruleDTO.setEndTime(end);
            ruleDTO.setRule(dto);
            ruleDTOList.add(ruleDTO);
        }
        return ruleDTOList;
    }

    /**
     * 构建基础fact
     * @param clientId
     * @param deviceId
     * @param productId
     * @return
     */
    private BaseFact buildBaseFact(String clientId, String deviceId, String productId){
        BaseFact fact = new BaseFact();
        fact.setClientId(clientId);
        fact.setProductId(productId);
        fact.setDeviceId(deviceId);
        return fact;
    }

    /**
     * 生成初始的设备信息
     * @param msg
     * @return
     */
    private DeviceFact buildDeviceFact(DeviceMsg msg){
        DeviceFact deviceFact = new DeviceFact();
        CopyUtil.copyPropertiesCglib(msg, deviceFact);
        return deviceFact;
    }

}
